#pragma once
#include <boost/lexical_cast.hpp>
#include <string>
#include <hiredis/hiredis.h>
#include <vector>
#include "tinyrpc/net/channel/socketchannel.h"
namespace TinyRPC{




class RedisClient{
public:
    RedisClient() : m_context(nullptr){};
    ~RedisClient() {
        if(m_context) {
            redisFree(m_context); 
        }
    }
    bool init(const std::string& ip, uint32_t port){
        m_context = redisConnect(ip.c_str(), port);
        if(m_context->err) {
            redisFree(m_context); 
            printf("connect redisServer err:%s\n", m_context->errstr);
            return false;
        } 
        return true;
    }

    bool redisCommandSuccess(redisContext *c, const char *format, ...);
    std::vector<std::string> redisCommandArray(redisContext *c, const char *format, ...);

    // key的一些操作
    bool expire(const std::string& key , int seconds);
    bool exists (const std::string& key);
    // string  操作
    bool set(const std::string& key, const std::string& value);
    std::string get(const std::string& key);
    bool setex (const std::string&  key, int seconds , const std::string&value);
    bool incr(const std::string& key);
    bool incrby(const std::string& key, long increment );
    bool incrbyfloat (const std::string&  key, float increment);
    
    // list 操作
    bool rpush(const std::string& key, const std::string& value);

    // hash 操作
    bool hset(const std::string& key, const std::string& field, const std::string& value);
    bool hdel(const std::string& key, const std::string& field);
    std::vector<std::string> hgetall(const std::string& key);
    //订阅 发布
    BufferPtr coroutine_subscribe( SocketChannel socketChannel, std::vector<std::string> channels){
        channels.insert(channels.begin(), "subscribe");
        std::string sendString = getRedisString(channels);
        socketChannel.write(sendString);
        return socketChannel.read();
    }

    BufferPtr keyevent_subscribe( SocketChannel socketChannel, std::string type){
        std::vector<std::string> cmds;
        cmds.push_back(" __keyevent@0__:" + type);
        std::string sendString = getRedisString(cmds);
        socketChannel.write(sendString);
        return socketChannel.read();
    }

    std::string getRedisString(std::vector<std::string> strs){
        std::string str = "";
        str += "*"+boost::lexical_cast<std::string>(strs.size()) + "\r\n";
        for(int i=0;i<strs.size();i++){
            str += "$"+boost::lexical_cast<std::string>(strs[i].size()) + "\r\n";
            str += strs[i]+ "\r\n";
        }
        return str;
    }



private:
    redisContext * m_context;
};

}
